package com.ymatou.iapi.productprice.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.ymatou.iapi.itempriceq.service.GetPriceByProdIdCall;
import com.ymatou.iapi.listpriceq.service.GetPriceByCatalogIdsCall;
import com.ymatou.iapi.listpriceq.service.GetPriceByCatalogIdsTradeIsolationCall;
import com.ymatou.iapi.listpriceq.service.GetPriceByProdIdsCall;
import com.ymatou.iapi.listpriceq.service.GetPriceByProdIdsTradeIsolationCall;
import com.ymatou.iapi.productprice.parameter.CatalogPriceBean;
import com.ymatou.iapi.productprice.parameter.ProductPriceBean;
import com.ymttest.utils.FileUtil;
import com.ymttest.utils.MapUtil;
import com.ymttest.utils.YMTDateUtil;

public class ComparePrice {

	public static String folder = "D:\\compare\\data";
	public static String errorFile = folder + "\\productprice\\error.txt";
	public static String diffFile = folder + "\\productprice\\diff.txt";
	public static String retFile = folder + "\\productprice\\ret.txt";

	// 老价格 服务接口
	public PriceInterface old_ByCatalogIds = new GetPriceByCatalogIdsCall();

	public PriceInterface old_ByCatalogIdsTradeIsolation = new GetPriceByCatalogIdsTradeIsolationCall();

	public PriceInterface old_ByProdIds = new GetPriceByProdIdsCall();

	public PriceInterface old_ByProdIdsTradeIsolation = new GetPriceByProdIdsTradeIsolationCall();

	public PriceInterface old_ByProdId = new GetPriceByProdIdCall();

	public PriceInterface old_ByProdIdTradeIsolation = new GetPriceByProdIdTradeIsolationCall();

	// 新价格服务 接口
	public PriceInterface new_ByCatalogIds = new com.ymatou.iapi.productprice.service.GetPriceByCatalogIdsCall();

	public PriceInterface new_ByCatalogIdsTradeIsolation = new com.ymatou.iapi.productprice.service.GetPriceByCatalogIdsTradeIsolationCall();

	public PriceInterface new_ByProdIds = new com.ymatou.iapi.productprice.service.GetPriceByProdIdsCall();

	public PriceInterface new_ByProdIdsTradeIsolation = new com.ymatou.iapi.productprice.service.GetPriceByProdIdsTradeIsolationCall();

	public PriceInterface new_ByProdId = new com.ymatou.iapi.productprice.service.GetPriceByProdIdCall();

	public PriceInterface new_ByProdIdTradeIsolation = new com.ymatou.iapi.productprice.service.GetPriceByProdIdTradeIsolationCall();

	//多物流
	public com.ymatou.iapi.listpriceq.service.GetCatalogPriceListByDeliveryExtraCall old_Mutli = new com.ymatou.iapi.listpriceq.service.GetCatalogPriceListByDeliveryExtraCall();
	
	public GetCatalogPriceListByDeliveryExtraCall new_Mutli = new GetCatalogPriceListByDeliveryExtraCall();
	
	public com.ymatou.iapi.listpriceq.service.GetCatalogPriceListByDeliveryTradeIsolationCall old_MutiTradeIsolation = new com.ymatou.iapi.listpriceq.service.GetCatalogPriceListByDeliveryTradeIsolationCall();
	
	public GetCatalogPriceListByDeliveryTradeIsolationCall new_MutiTradeIsolation = new GetCatalogPriceListByDeliveryTradeIsolationCall();
	
	
	//===========================================================================================================================
	
	
	
	public static void compare(PriceInterface oldInterface, PriceInterface newInterface, int buyerId,
			String productIdOrCatalogId, String funticonname) throws JSONException {

		System.out.println("[" + funticonname + "]");

		JSONObject oldRet = oldInterface.GetReturnDataByBuyerAndId(buyerId, productIdOrCatalogId);
		JSONObject newRet = newInterface.GetReturnDataByBuyerAndId(buyerId, productIdOrCatalogId);

		try {

			ProductPriceBean oldPrice = getPriceBeanByRet(oldRet);
			ProductPriceBean newPrice = getPriceBeanByRet(newRet);
			String productId = oldPrice.getProductId();
			oldPrice.getCatalogPriceBeans().parallelStream().forEach(ele -> {
				CatalogPriceBean newCatalogPriceBean = newPrice.getCatalogPriceBeans().stream()
						.filter(newEle -> newEle.getCatalogId().equals(ele.getCatalogId())).findAny().orElse(null);

				if (newCatalogPriceBean == null) {
					System.out.println("规格id:" + ele.getCatalogId() + ",在新接口返回报文中不存在");
				} else {
					if (ele.getPrice() == newCatalogPriceBean.getPrice()) {
						
						/*  System.out.println("[" + funticonname +
						  "]价格一致,  ProductId:" + productId + ",  CatalogId:" +
						  ele.getCatalogId() + ", 价格比对  老接口价格:" +
						  ele.getPrice() + ",新接口价格:" +
						  newCatalogPriceBean.getPrice());*/
						  
						  
		/*				 FileUtil.writeAsLine(retFile, "[" + funticonname +
						  "] 价格一致,  ProductId:" + productId + ",  CatalogId:" +
						 ele.getCatalogId() + ", 老接口价格:" +
						  ele.getPrice() + ",新接口价格:" +
						  newCatalogPriceBean.getPrice());*/
						
/*						FileUtil.writeAsLine(retFile,productId+",一致");*/
						 

					} else {
						
						/*  System.out.println("####[" + funticonname +
						  "] 价格不一致, ProductId:" + productId + ",CatalogId:" +
						  ele.getCatalogId() + ", 价格比对  老接口价格:" +
						  ele.getPrice() + ",新接口价格:" +
						  newCatalogPriceBean.getPrice());*/
						 

						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] 价格不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ", 价格比对  老接口价格:" + ele.getPrice() + ",新接口价格:"
										+ newCatalogPriceBean.getPrice());
					}
					
					
					if (ele.getPriceType() == newCatalogPriceBean.getPriceType()){
						
					}else{
						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] PriceType不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ",   老接口PriceType:" + ele.getPriceType() + ",新接口PriceType:"
										+ newCatalogPriceBean.getPriceType());
					}
				}

			});
		} catch (Exception e) {
			FileUtil.writeAsLine(errorFile, productIdOrCatalogId + ", " + funticonname + ",Old_Msg"
					+ oldRet.getString("Msg") + ",New_Msg" + newRet.getString("Msg"));
			e.printStackTrace();
		}

	}

	
	public static void compareMutli(String catalogId,JSONObject oldRet,JSONObject newRet,String funticonname){
		try {
			if (oldRet.isNull("Data")){
				FileUtil.writeAsLine(errorFile, catalogId + ", " + funticonname + ",不存在");
				return;
			}
			
			ProductPriceBean oldPrice = getPriceBeanByRet(oldRet);
			ProductPriceBean newPrice = getPriceBeanByRet(newRet);
			String productId = oldPrice.getProductId();
			oldPrice.getCatalogPriceBeans().parallelStream().forEach(ele -> {
				CatalogPriceBean newCatalogPriceBean = newPrice.getCatalogPriceBeans().stream()
						.filter(newEle -> newEle.getCatalogId().equals(ele.getCatalogId())).findAny().orElse(null);

				if (newCatalogPriceBean == null) {
					System.out.println("规格id:" + ele.getCatalogId() + ",在新接口返回报文中不存在");
				} else {
					if (ele.getPrice() != newCatalogPriceBean.getPrice()) {
							FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] 价格不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ", 价格比对  老接口价格:" + ele.getPrice() + ",新接口价格:"
										+ newCatalogPriceBean.getPrice());
					}
					
					if (ele.getDeliveryType() != newCatalogPriceBean.getDeliveryType()) {
						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
							",[" + funticonname + "] DeliveryType不一致, ProductId:" + productId + ",CatalogId:"
									+ ele.getCatalogId() + ", 比对  老接口:" + ele.getDeliveryType() + ",新接口:"
									+ newCatalogPriceBean.getDeliveryType());
					}
					
					if (ele.getExtraDeliveryFeel() != newCatalogPriceBean.getExtraDeliveryFeel()) {
						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] ExtraDeliveryFeel不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ", 比对  老接口:" + ele.getExtraDeliveryFeel() + ",新接口:"
										+ newCatalogPriceBean.getExtraDeliveryFeel());
					}
					
					
					if (ele.getExtraDeliveryType() != newCatalogPriceBean.getExtraDeliveryType()) {
						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] ExtraDeliveryType 不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ", 比对  老接口:" + ele.getExtraDeliveryType() + ",新接口:"
										+ newCatalogPriceBean.getExtraDeliveryType());
					}
					
					if (ele.getPriceType() != newCatalogPriceBean.getPriceType()) {
						FileUtil.writeAsLine(diffFile,YMTDateUtil.getSysTime()+
								",[" + funticonname + "] PriceType 不一致, ProductId:" + productId + ",CatalogId:"
										+ ele.getCatalogId() + ", 比对  老接口:" + ele.getPriceType() + ",新接口:"
										+ newCatalogPriceBean.getPriceType());
					}
					
					
					
				}

			});
		} catch (Exception e) {
			try {
				FileUtil.writeAsLine(errorFile, catalogId + ", " + funticonname + ",Old_Msg"
						+ oldRet.getString("Msg") + ",New_Msg" + newRet.getString("Msg"));
			} catch (JSONException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	
	public static ProductPriceBean getPriceBeanByRet(JSONObject ret) throws Exception {
		JSONObject dataObj = ret.getJSONObject("Data");
		ProductPriceBean productPriceBean = new ProductPriceBean();

		if (dataObj.has("PriceInfo")) {
			// prodId
			JSONObject retBean = dataObj.getJSONObject("PriceInfo");
			String productId = retBean.getString("ProductId");
			productPriceBean.setProductId(productId);

			JSONArray catalogsJsonArray = retBean.getJSONArray("Catalogs");
			productPriceBean.setProductId(retBean.getString("ProductId"));

			List<CatalogPriceBean> catalogPriceBeans = new ArrayList<>();
			for (int i = 0; i < catalogsJsonArray.length(); i++) {
				JSONObject catalogInfo = catalogsJsonArray.getJSONObject(i);
				CatalogPriceBean aCatalogPriceBean = new CatalogPriceBean();
				aCatalogPriceBean.setCatalogId(catalogInfo.getString("CatalogId"));
				aCatalogPriceBean.setPrice(catalogInfo.getDouble("Price"));
				aCatalogPriceBean.setPriceType(catalogInfo.getInt("PriceType"));
				catalogPriceBeans.add(aCatalogPriceBean);
			}
			productPriceBean.setCatalogPriceBeans(catalogPriceBeans);

		} else if (dataObj.has("ProductPriceList")) {
			// prodId list
			JSONObject retBean = dataObj.getJSONArray("ProductPriceList").getJSONObject(0);
			String productId = retBean.getString("ProductId");
			productPriceBean.setProductId(productId);

			JSONArray catalogsJsonArray = retBean.getJSONArray("Catalogs");
			productPriceBean.setProductId(retBean.getString("ProductId"));

			List<CatalogPriceBean> catalogPriceBeans = new ArrayList<>();
			for (int i = 0; i < catalogsJsonArray.length(); i++) {
				JSONObject catalogInfo = catalogsJsonArray.getJSONObject(i);
				CatalogPriceBean aCatalogPriceBean = new CatalogPriceBean();
				aCatalogPriceBean.setCatalogId(catalogInfo.getString("CatalogId"));
				aCatalogPriceBean.setPrice(catalogInfo.getDouble("Price"));
				aCatalogPriceBean.setPriceType(catalogInfo.getInt("PriceType"));
				catalogPriceBeans.add(aCatalogPriceBean);
			}
			productPriceBean.setCatalogPriceBeans(catalogPriceBeans);

		} else if (dataObj.has("CatalogPriceList")) {
			// catalog list
			JSONArray CatalogPriceListArray = dataObj.getJSONArray("CatalogPriceList");
			String productId = CatalogPriceListArray.getJSONObject(0).getString("ProductId");

			// 组装报文返回值
			productPriceBean.setProductId(productId);

			List<CatalogPriceBean> catalogPriceBeans = new ArrayList<>();
			for (int i = 0; i < CatalogPriceListArray.length(); i++) {
				JSONObject tempCatalogInfo = CatalogPriceListArray.getJSONObject(i);
				JSONObject tempCatalog = tempCatalogInfo.getJSONObject("CatalogInfo");
				CatalogPriceBean aCatalogPriceBean = new CatalogPriceBean();
				
				aCatalogPriceBean.setCatalogId(tempCatalog.getString("CatalogId"));
				aCatalogPriceBean.setPrice(tempCatalog.getDouble("Price"));
				aCatalogPriceBean.setPriceType(tempCatalog.getInt("PriceType"));
				
				if (tempCatalog.has("DeliveryType")){
					aCatalogPriceBean.setDeliveryType(tempCatalog.getInt("DeliveryType"));
				}
				
				if (tempCatalog.has("ExtraDeliveryType")){
					aCatalogPriceBean.setDeliveryType(tempCatalog.getInt("ExtraDeliveryType"));
				}
				
				if (tempCatalog.has("ExtraDeliveryFee")){
					aCatalogPriceBean.setDeliveryType(tempCatalog.getInt("ExtraDeliveryFee"));
				}
				
				
				catalogPriceBeans.add(aCatalogPriceBean);
			}
			productPriceBean.setCatalogPriceBeans(catalogPriceBeans);
		}

		return productPriceBean;
	}

	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////
	public static void checkPriceByProd(List<Integer> userIds, List<String> productIds) {

		userIds.forEach(userId -> {
			productIds.forEach(prodId -> {
				System.out.println("BuyId:" + userId + ",  ProductId:" + prodId);

				// compare(new ComparePrice().old_ByProdIds, new
				// ComparePrice().new_ByProdIds,
				// userId,prodId,"GetPriceByProdIds");

				// compare(new ComparePrice().old_ByProdIdsTradeIsolation, new
				// ComparePrice().new_ByProdIdsTradeIsolation, userId,
				// prodId,"GetPriceByProdIdsTradeIsolation");

				try {
					compare(new ComparePrice().old_ByProdId, new ComparePrice().new_ByProdId, userId, prodId,"GetPriceByProdId");
					compare(new ComparePrice().old_ByProdId, new ComparePrice().new_ByProdId, userId, prodId,"GetPriceByProdId");
					//compare(new ComparePrice().old_ByProdIdTradeIsolation,new ComparePrice().new_ByProdIdTradeIsolation, userId,prodId,"GetPriceByProdIdTradeIsolation");
					//compare(new ComparePrice().old_ByProdIds, new ComparePrice().new_ByProdIds,userId,prodId,"GetPriceByProdIds");
					//compare(new ComparePrice().old_ByProdIdsTradeIsolation, new ComparePrice().new_ByProdIdsTradeIsolation, userId, prodId,"GetPriceByProdIdsTradeIsolation");
				
				} catch (JSONException e) {
					e.printStackTrace();
				}

				System.out.println("\n");

			});
		});
	}  

	public static void checkPriceByCatalog(List<Integer> userIds, List<String> catalogIds) {
		userIds.forEach(userId -> {
			catalogIds.forEach(catalogId -> {
				System.out.println("BuyId:" + userId + ",  CatalogId:" + catalogId);

				try {
					compare(new ComparePrice().old_ByCatalogIds, new ComparePrice().new_ByCatalogIds, userId, catalogId,"GetPriceByCatalogIds");
					compare(new ComparePrice().old_ByCatalogIdsTradeIsolation,new ComparePrice().new_ByCatalogIdsTradeIsolation, userId, catalogId,"GetPriceByCatalogIdsTradeIsolation");
				} catch (JSONException e) {
					e.printStackTrace();
				}

				System.out.println("\n");

			});
		});

	}

	
	public static void checkPriceByMultiLogistics(List<Integer> userIds, List<String> catalogIds){
		int[] logisticsList = new int[]{2,3};
		
		userIds.forEach(userId->{
			for(int i=0;i<logisticsList.length;i++){
				int logistics = logisticsList[i];
				catalogIds.forEach(catalogId->{
					System.out.println("BuyId:" + userId + ",  CatalogId:" + catalogId + ", LogistId: "+logistics);
					Map<String,Integer> catalogsMap = MapUtil.hashMap(catalogId, logistics);
					
					//交易不隔离
					String funticonname = "GetCatalogPriceListByDeliveryExtra";
					System.out.println("[" + funticonname + "]");

					JSONObject oldRet = new ComparePrice().old_Mutli.callAndGetReturnData(userId, catalogsMap);
					JSONObject newRet = new ComparePrice().new_Mutli.callAndGetReturnData(userId, catalogsMap);
					compareMutli(catalogId,oldRet,newRet,funticonname);
					
					//交易隔离
					String funticonname2 = "GetCatalogPriceListByDeliveryExtra";
					System.out.println("[" + funticonname2 + ", 物流类型: "+ logistics +"]");

					JSONObject oldRet2 = new ComparePrice().old_MutiTradeIsolation.callAndGetReturnData(userId, catalogsMap);
					JSONObject newRet2 = new ComparePrice().new_MutiTradeIsolation.callAndGetReturnData(userId, catalogsMap);
					compareMutli(catalogId,oldRet2,newRet2,funticonname2);
					
				});
				
				
			}
			
		});
		
		
		System.out.println("\n");
		
	}
	
	
	
	
	
	public static <T> List<List<T>> splitCollectionToCollectionList(List<T> objectList, Integer splitNum) {

		int splitTimes = (objectList.size() + splitNum - 1) / splitNum;

		List<List<T>> resultCollection = new ArrayList<>();

		for (int i = 0; i < splitTimes; i++) {
			List<T> subObjectList = objectList.stream().skip(splitNum * i).limit(splitNum).collect(Collectors.toList());
			resultCollection.add(subObjectList);
		}

		return resultCollection;
	}

	public static void main(String[] args) throws InterruptedException {
		//每組個數
		int group = 6000;
		
		Date startDate = YMTDateUtil.getDate();
		FileUtil.deleteFile(errorFile);
		FileUtil.deleteFile(diffFile);
		FileUtil.deleteFile(retFile);

		String userPath = folder + "\\userId.txt";
		String productPath = folder + "\\productId.txt";
		String catalogPath = folder +"\\catalogId.txt"; 

		List<Integer> userIdsFromFile = new ArrayList<>();
		FileUtil.readFileAsLine(userPath).forEach(ele -> userIdsFromFile.add(Integer.parseInt(ele)));

		
		List<String> productsFromFile = FileUtil.readFileAsLine(productPath);
		

		List<String>  catalogsFromFile = FileUtil.readFileAsLine(catalogPath);
		
/*		checkPriceByProd(userIdsFromFile, productsFromFile);
		checkPriceByCatalog(userIdsFromFile, catalogsFromFile);*/
		 
		
		
	 	List<List<String>> productsFromFileAry = splitCollectionToCollectionList(productsFromFile, group);
	 	List<List<String>> catalogsFromFileAry = splitCollectionToCollectionList(catalogsFromFile, group);

		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, Long.MAX_VALUE, TimeUnit.SECONDS,new LinkedBlockingQueue<>());

		for (int i = 0; i < productsFromFileAry.size(); i++) {
			List<String> tmp = productsFromFileAry.get(i);
			threadPoolExecutor.execute(new Runnable() {
				@Override
				public void run() {
					checkPriceByProd(userIdsFromFile, tmp);
				}
			});

		}

		
		for (int i = 0; i < catalogsFromFileAry.size(); i++) {
			List<String> tmp = catalogsFromFileAry.get(i);
			threadPoolExecutor.execute(new Runnable() {
				@Override
				public void run() {
					checkPriceByMultiLogistics(userIdsFromFile, tmp);
				}
			});

		}
		
		
		threadPoolExecutor.shutdown();// 只是不能再提交新任务，等待执行的任务不受影响

		
		try {
			boolean loop = true;
			do { // 等待所有任务完成
				loop = !threadPoolExecutor.awaitTermination(1, TimeUnit.SECONDS); // 阻塞，直到线程池里所有任务结束
			} while (loop);

			
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		
		Date endDate = YMTDateUtil.getDate();
		System.out.println((endDate.getTime() - startDate.getTime()) / 1000);
		System.out.println(endDate);

		
		
		
		
		
	

	}
}
